{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vUXNQZtwEYiQ"
      },
      "source": [
        "# Running MegaDetector on camera trap images\n",
        "\n",
        "[Open this notebook in Colab](https://colab.research.google.com/github/agentmorris/MegaDetector/blob/main/notebooks/megadetector_colab.ipynb)\n",
        "\n",
        "Adapted from previous versions by [@louis030195](https://github.com/louis030195)\n",
        "and [@alsnothome](https://github.com/alsnothome).\n",
        "\n",
        "Also see the [MegaDetector guide on GitHub](https://github.com/agentmorris/MegaDetector/blob/main/megadetector.md) and the [MegaDetector Python package documentation](https://megadetector.readthedocs.io).\n",
        "\n",
        "This notebook is designed to load camera trap images that have already been uploaded to Google Drive. If you don't have your own images on Google Drive, this notebook will show you how to download some sample images from [LILA](https://lila.science).\n",
        "\n",
        "MegaDetector output is saved in a .json file whose format is described  [here](https://github.com/agentmorris/MegaDetector/tree/main/megadetector/api/batch_processing#batch-processing-api-output-format). The last cell in this notebook will give you some pointers on how users typically work with MegaDetector output."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9aUlxnm7cnWy"
      },
      "source": [
        "## Set up the Colab instance to run on a GPU accelerator\n",
        "\n",
        "\n",
        "Navigate to Edit→Notebook Settings and select \"GPU\" from the \"Hardware accelerator\" drop-down menu."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VtNnMxtte0EF"
      },
      "source": [
        "## Install the MegaDetector Python package\n",
        "\n",
        "This may take 2-3 minutes.  You may be asked to re-start the Colab runtime, that's OK."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "EMEkgpy6T0pr"
      },
      "outputs": [],
      "source": [
        "pip install megadetector"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "JyjEgkCsOsak"
      },
      "source": [
        "## Mount Google Drive in Colab\n",
        "You can mount your Google Drive if you have your sample images there, or if want to save the results to your Google Drive.  \n",
        "\n",
        "Once you run the cell below, you will be prompted to authorize Colab to access your Google Drive.  Your Google Drive folders will then be mounted under `/content/drive` and can be viewed and navigated in the Files pane in Colab.\n",
        "\n",
        "The method is described in [this Colab code snippet](https://colab.research.google.com/notebooks/io.ipynb#scrollTo=u22w3BFiOveA)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "XYsrTTR7eF0r"
      },
      "outputs": [],
      "source": [
        "from google.colab import drive\n",
        "drive.mount('/content/drive')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "yM3Dl0Bfe0EM"
      },
      "source": [
        "## Download sample images\n",
        "\n",
        "We install Microsoft's [azcopy](https://docs.microsoft.com/en-us/azure/storage/common/storage-use-azcopy-v10) utility, which we then use to download a few camera trap images from the [Snapshot Serengeti](http://lila.science/datasets/snapshot-serengeti) dataset hosted on [lila.science](http://lila.science).  If you are using your own data, you can skip this step."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "gAkYScsLe0EM"
      },
      "outputs": [],
      "source": [
        "%%bash\n",
        "\n",
        "# Download azcopy\n",
        "wget -q -O azcopy_linux.tar.gz https://aka.ms/downloadazcopy-v10-linux\n",
        "tar -xvzf azcopy_linux.tar.gz --wildcards */azcopy --strip 1\n",
        "rm azcopy_linux.tar.gz\n",
        "chmod u+x azcopy\n",
        "\n",
        "# Copy a few Snapshot Serengeti images to a local directory\n",
        "DATASET_URL=\"https://lilawildlife.blob.core.windows.net/lila-wildlife/snapshotserengeti-unzipped/\"\n",
        "SAMPLE_DIR=\"S1/D05/D05_R4\"\n",
        "LOCAL_DIR=\"/content/snapshotserengeti\"\n",
        "\n",
        "./azcopy cp \"${DATASET_URL}${SAMPLE_DIR}\" \"${LOCAL_DIR}\" --recursive"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "3YZs9wT1sAgV"
      },
      "source": [
        "## Run the detection script\n",
        "\n",
        "This step executes the Python script `run_detector_batch.py` from the MegaDetector package. It has three mandatory arguments and one optional:\n",
        "\n",
        "1. A MegaDetector model file (this can be a model name, like \"MDV5A\", or a path to a model file).\n",
        "2. A folder containing images.  This notebook points to the folder where we just put our Snapshot Serengeti images; if your images were already on Google Drive, replace `[Image_Folder]` with your folder name.\n",
        "3. The output JSON file location and name.\n",
        "\n",
        "There are actually two variants of MegaDetector v5, called \"v5a\" and \"v5b\".  By default this notebook runs MDv5a; change \"MDV5A\" to \"MDV5B\" below to run MDv5b instead.\n",
        "\n",
        "Both run at the same speed; if you are in a Colab session with a GPU accelerator, you should be able to process around four images per second.\n",
        "\n",
        "Here we are running MegaDetector using python -m to invoke the module as if we were running it at the command line.  You can call this directly via Python code as well; documentation for this module is available [here](https://megadetector.readthedocs.io/en/latest/detection.html#module-megadetector.detection.run_detector_batch).\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "3AOKfviGuTNg"
      },
      "outputs": [],
      "source": [
        "# Choose a folder of images to process\n",
        "images_dir = '/content/snapshotserengeti'\n",
        "\n",
        "# Choose a location for the output JSON file\n",
        "output_file_path = '/content/drive/My Drive/snapshotserengeti-test/snapshot-serengeti-megadetector-results.json'\n",
        "\n",
        "# Run MegaDetector\n",
        "!python -m megadetector.detection.run_detector_batch \"MDV5A\" \"$images_dir\" \"$output_file_path\" --recursive --output_relative_filenames --quiet"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "-tHu5WUGDpcd"
      },
      "source": [
        "## Visualize batch processing script outputs\n",
        "\n",
        "Here we use the `visualize_detector_output.py` in the `visualization` folder of the MegaDetector repo to see the output of the MegaDetector visualized on our images. It will save images annotated with the results (original images will *not* be modified) to the folder you specify here."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "en3TbCftkWDE"
      },
      "outputs": [],
      "source": [
        "# Render bounding boxes on our images\n",
        "visualization_dir = '/content/visualized_images'\n",
        "!python -m megadetector.visualization.visualize_detector_output \"$output_file_path\" \"$visualization_dir\" --confidence 0.2 --images_dir \"$images_dir\""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "AglNEK0goyjA"
      },
      "outputs": [],
      "source": [
        "# Show the images with bounding boxes in Colab\n",
        "import os\n",
        "from PIL import Image\n",
        "\n",
        "for viz_file_name in os.listdir(visualization_dir):\n",
        "  print(viz_file_name)\n",
        "  im = Image.open(os.path.join(visualization_dir, viz_file_name))\n",
        "  display(im)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ycce0Oi_e0EQ"
      },
      "source": [
        "# Next steps\n",
        "\n",
        "Now that you have run MegaDetector on a few images, here are some pointers to help you take advantage of MegaDetector to label your survey images more quickly.\n",
        "\n",
        "### Ways to use the output .json in a camera trap image processing workflow\n",
        "\n",
        "#### 1. Timelapse\n",
        "\n",
        "[Timelapse](http://saul.cpsc.ucalgary.ca/timelapse/pmwiki.php?n=Main.HomePage) is an open-source tool for annotating camera trap images. We have worked with the Timelapse developer to integrate MegaDetector results into Timelapse, so a user can:\n",
        "\n",
        "- Select or sort images based on whether they contain animal or people or vehicles.\n",
        "- View bounding boxes during additional manual annotation steps\n",
        "\n",
        "See the [Timelapse Image Recognition Guide](https://saul.cpsc.ucalgary.ca/timelapse/uploads/Guides/TimelapseImageRecognitionGuide.pdf) for more information.\n",
        "\n",
        "![Screenshot showing the Timelapse application with MegaDetector output, shown as a bounding box around the detected animal](https://github.com/agentmorris/MegaDetector/blob/main/megadetector/api/batch_processing/integration/images/tl_boxes.jpg?raw=1)\n",
        "\n",
        "\n",
        "#### 2. Separating images into folders that contain animals/people/vehicles/nothing\n",
        "\n",
        "Some MegaDetector users do image review without Timelapse, by moving the images to separate folders containing animals/people/vehicles/nothing according to MegaDetector output. You can use the script [separate_detections_into_folders.py](https://github.com/agentmorris/MegaDetector/blob/main/megadetector/postprocessing/separate_detections_into_folders.py) for this.\n",
        "\n"
      ]
    }
  ],
  "metadata": {
    "accelerator": "GPU",
    "colab": {
      "provenance": [],
      "toc_visible": true,
      "gpuType": "T4"
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.11.9"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}